package com.mini.grpc.examples.helloworld;

import com.mini.grpc.client.ManagedChannel;
import com.mini.grpc.client.ManagedChannelBuilder;
import com.mini.grpc.server.Server;
import com.mini.grpc.server.ServerBuilder;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Logger;
import java.util.Arrays;
import java.util.List;

/**
 * HelloWorld 完整演示
 * 
 * 这个类演示了如何：
 * 1. 启动 gRPC 服务端
 * 2. 创建客户端连接
 * 3. 执行各种类型的 gRPC 调用
 * 4. 优雅关闭服务端和客户端
 * 
 * 这是一个完整的、可运行的示例，方便分析 Mini-gRPC 的调用流程
 */
public class HelloWorldDemo {
    
    private static final Logger logger = Logger.getLogger(HelloWorldDemo.class.getName());
    private static final int SERVER_PORT = 50051;
    
    private Server server;
    private ManagedChannel channel;
    private HelloWorldClient client;
    private ExecutorService executor;
    
    /**
     * 启动演示
     */
    public void start() throws IOException, InterruptedException {
        logger.info("🚀 开始 Mini-gRPC HelloWorld 完整演示");
        logger.info("=" .repeat(60));
        
        // 1. 启动服务端
        startServer();
        
        // 2. 等待服务端完全启动
        Thread.sleep(1000);
        
        // 3. 创建客户端
        createClient();
        
        // 4. 执行各种调用演示
        runDemonstrations();
        
        logger.info("=" .repeat(60));
        logger.info("✅ Mini-gRPC HelloWorld 演示完成");
    }
    
    /**
     * 启动服务端
     */
    private void startServer() throws IOException {
        logger.info("📡 启动 gRPC 服务端...");
        
        HelloWorldServiceImpl serviceImpl = new HelloWorldServiceImpl();
        
        server = ServerBuilder.forPort(SERVER_PORT)
            .addService(serviceImpl.bindService())
            .build()
            .start();
        
        logger.info(String.format("✅ 服务端已启动，监听端口: %d", SERVER_PORT));
        
        // 添加关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            logger.info("🛑 检测到关闭信号，正在关闭服务...");
            HelloWorldDemo.this.shutdown();
        }));
    }
    
    /**
     * 创建客户端
     */
    private void createClient() {
        logger.info("🔗 创建 gRPC 客户端连接...");
        
        String target = "localhost:" + SERVER_PORT;
        channel = ManagedChannelBuilder.forTarget(target)
            .usePlaintext()
            .build();
        
        client = new HelloWorldClient(channel);
        
        logger.info("✅ 客户端连接已建立");
    }
    
    /**
     * 执行各种调用演示
     */
    private void runDemonstrations() throws InterruptedException {
        logger.info("\n🎯 开始执行各种 gRPC 调用演示...\n");
        
        // 演示1: 一元调用
        demonstrateUnaryCall();
        
        // 演示2: 服务端流式调用
        demonstrateServerStreaming();
        
        // 演示3: 客户端流式调用
        demonstrateClientStreaming();
        
        // 演示4: 双向流式调用
        demonstrateBidirectionalStreaming();
        
        // 演示5: 并发调用
        demonstrateConcurrentCalls();
    }
    
    /**
     * 演示一元调用
     */
    private void demonstrateUnaryCall() throws InterruptedException {
        logger.info("📞 演示1: 一元调用 (Unary Call)");
        logger.info("-".repeat(40));
        
        client.demonstrateUnaryCall("张三");
        Thread.sleep(500);
        
        client.demonstrateUnaryCall("李四");
        Thread.sleep(500);
        
        client.demonstrateUnaryCall("王五");
        
        logger.info("✅ 一元调用演示完成\n");
        Thread.sleep(1000);
    }
    
    /**
     * 演示服务端流式调用
     */
    private void demonstrateServerStreaming() throws InterruptedException {
        logger.info("📡 演示2: 服务端流式调用 (Server Streaming)");
        logger.info("-".repeat(40));
        
        client.demonstrateServerStreamingCall("赵六");
        
        logger.info("✅ 服务端流式调用演示完成\n");
        Thread.sleep(1000);
    }
    
    /**
     * 演示客户端流式调用
     */
    private void demonstrateClientStreaming() throws InterruptedException {
        logger.info("📤 演示3: 客户端流式调用 (Client Streaming)");
        logger.info("-".repeat(40));
        
        List<String> names = Arrays.asList("孙七", "周八", "吴九", "郑十");
        client.demonstrateClientStreamingCall(names);
        
        logger.info("✅ 客户端流式调用演示完成\n");
        Thread.sleep(1000);
    }
    
    /**
     * 演示双向流式调用
     */
    private void demonstrateBidirectionalStreaming() throws InterruptedException {
        logger.info("🔄 演示4: 双向流式调用 (Bidirectional Streaming)");
        logger.info("-".repeat(40));
        
        List<String> names = Arrays.asList("冯一", "陈二", "褚三");
        client.demonstrateBidirectionalStreamingCall(names);
        
        logger.info("✅ 双向流式调用演示完成\n");
        Thread.sleep(1000);
    }
    
    /**
     * 演示并发调用
     */
    private void demonstrateConcurrentCalls() throws InterruptedException {
        logger.info("⚡ 演示5: 并发调用 (Concurrent Calls)");
        logger.info("-".repeat(40));
        
        executor = Executors.newFixedThreadPool(3);
        
        try {
            // 提交3个并发的一元调用
            Future<?> future1 = executor.submit(() -> {
                client.demonstrateUnaryCall("并发用户A");
            });
            
            Future<?> future2 = executor.submit(() -> {
                client.demonstrateUnaryCall("并发用户B");
            });
            
            Future<?> future3 = executor.submit(() -> {
                client.demonstrateUnaryCall("并发用户C");
            });
            
            // 等待所有调用完成
            future1.get();
            future2.get();
            future3.get();
            
            logger.info("✅ 并发调用演示完成\n");
            
        } catch (Exception e) {
            logger.severe("并发调用演示失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            if (executor != null) {
                executor.shutdown();
                executor.awaitTermination(5, TimeUnit.SECONDS);
            }
        }
    }
    
    /**
     * 关闭所有资源
     */
    public void shutdown() {
        logger.info("🛑 正在关闭演示程序...");
        
        try {
            // 关闭客户端
            if (client != null) {
                client.shutdown();
            }
            
            // 关闭通道
            if (channel != null) {
                channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
            }
            
            // 关闭线程池
            if (executor != null && !executor.isShutdown()) {
                executor.shutdown();
                executor.awaitTermination(5, TimeUnit.SECONDS);
            }
            
            // 关闭服务端
            if (server != null) {
                server.shutdown();
                if (!server.awaitTermination(10, TimeUnit.SECONDS)) {
                    logger.warning("服务端未能在10秒内关闭，强制关闭");
                    server.shutdownNow();
                }
            }
            
            logger.info("✅ 所有资源已关闭");
            
        } catch (InterruptedException e) {
            logger.warning("关闭过程被中断: " + e.getMessage());
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * 主方法
     * 
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        HelloWorldDemo demo = new HelloWorldDemo();
        
        try {
            // 启动演示
            demo.start();
            
            // 等待用户输入或5分钟后自动关闭
            logger.info("演示程序将在5分钟后自动关闭，或按 Ctrl+C 立即停止");
            Thread.sleep(300000); // 5分钟
            
        } catch (InterruptedException e) {
            logger.info("演示程序被中断");
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            logger.severe("演示程序发生错误: " + e.getMessage());
            e.printStackTrace();
        } finally {
            demo.shutdown();
        }
    }
} 